package org.dingyom.user.service.impl;

import org.apache.commons.lang3.StringUtils;
import org.dingyom.basics.constants.LogininfoConstants;
import org.dingyom.basics.constants.SmsContants;
import org.dingyom.basics.util.AjaxResult;
import org.dingyom.basics.util.MD5Utils;
import org.dingyom.user.domain.Logininfo;
import org.dingyom.user.dto.LoginDto;
import org.dingyom.user.dto.NoteDto;
import org.dingyom.user.mapper.LogininfoMapper;
import org.dingyom.user.service.ILogininfoService;
import org.dingyom.basics.service.impl.BaseServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author dingyom
 * @since 2022-09-15
 */
@Service
public class LogininfoServiceImpl extends BaseServiceImpl<Logininfo> implements ILogininfoService {

    @Autowired
    LogininfoMapper logininfoMapper;
    @Autowired
    RedisTemplate redisTemplate;
    @Override
    public AjaxResult account(LoginDto dto) {
        String username = dto.getUsername();
        String password = dto.getPassword();
        Integer type = dto.getType();
        //判空
        if (StringUtils.isEmpty(username)||StringUtils.isEmpty(password)||type==null)
            return AjaxResult.me().setSuccess(false).setMessage("登陆失败，参数异常");
        //查询登陆用户是否存在
        Logininfo loginUser = logininfoMapper.loadByInfo(dto);
        if (loginUser == null) {
            return AjaxResult.me().setSuccess(false).setMessage("用户名或密码错误，请重新登陆！");
        }
        //查询登陆用户状态是否可用
        if (loginUser.getDisable() != LogininfoConstants.LOGININFO_DISABLE_YES)
            return AjaxResult.me().setSuccess(false).setMessage("该账户已被冻结，请联系客服");

        //将前台传进来的密码加盐加密 与查询出来的密码进行对比
        String salt = loginUser.getSalt();
        String pwd = password + salt;
        String securityPwd = MD5Utils.encrypByMd5(pwd);//前台加密的密码
        if (!securityPwd.equals(loginUser.getPassword()))
            return AjaxResult.me().setSuccess(false).setMessage("用户名或密码错误，请重新登陆！");

        //记录logininfo到redis中 ， key是token,设置30分钟后过期
        String token = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(token, loginUser, 30, TimeUnit.MINUTES);
        //登陆成功 要将token和loginfo返回
        Map<String,Object> result= new HashMap<>();
        result.put("token", token);
        //注意 返回登陆用户信息时 为了安全性，要将私密的信息置空 比如密码 和 盐值
        loginUser.setPassword(null);
        loginUser.setSalt(null);
        result.put("loginUser", loginUser);
        return AjaxResult.me().setData(result);
    }

    @Override
    public AjaxResult accountBySms(NoteDto dto) {
        String mobile = dto.getMobile();
        String smsCode = dto.getSmsCode();
        //判空
        if (StringUtils.isEmpty(mobile)||StringUtils.isEmpty(smsCode)){
            return AjaxResult.me().setSuccess(false).setMessage("登陆失败，参数异常");
        }
        //判断是否存在用户
        Logininfo loginUser = logininfoMapper.loadByPhone(mobile);
        if (loginUser == null) {
            return AjaxResult.me().setSuccess(false).setMessage("用户名或密码错误，请重新登陆！");
        }
        //查询登陆用户状态是否可用
        if (loginUser.getDisable() != LogininfoConstants.LOGININFO_DISABLE_YES)
            return AjaxResult.me().setSuccess(false).setMessage("该账户已被冻结，请联系客服");
        //比对验证码
        String key = SmsContants.SMSCODE_KEY+mobile;
        String smsCodeOfRedis = (String)redisTemplate.opsForValue().get(key);
        if (StringUtils.isEmpty(smsCodeOfRedis)||!smsCodeOfRedis.split(":")[0].equals(smsCode)){
            return AjaxResult.me().setSuccess(false).setMessage("验证码错误或已经过期！");
        }

        //记录logininfo到redis中 ， key是token,设置30分钟后过期
        String token = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(token, loginUser, 30, TimeUnit.MINUTES);
        //登陆成功 要将token和loginfo返回
        Map<String,Object> result= new HashMap<>();
        result.put("token", token);
        //注意 返回登陆用户信息时 为了安全性，要将私密的信息置空 比如密码 和 盐值
        loginUser.setPassword(null);
        loginUser.setSalt(null);
        result.put("loginUser", loginUser);
        return AjaxResult.me().setData(result);
    }
}
